﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Controls;

namespace MuzičkiFeršterker
{
    public class PlayList
    {
        #region SETTINGS VALUES
        private readonly int S_maxShuffleLength = 100;
        #endregion

        public class PlayListLine
        {
            public string Queue { get; set; }
            public string Length { get; set; }
            public string Title { get; set; }
        }

        private List<Song> filesList;
        private List<int> shuffleHistory;
        private List<int> queuedFiles;
        private ListView playlistView;
        private int songCount;

        private int currentFileIndex;

        private bool shuffle;
        private int currentShufflePosition;

        #region Constructors
        public PlayList(string file, ListView listView)
            : this(listView)
        {
            Add(file);
        }

        public PlayList(string[] files, ListView listView)
            : this(listView)
        {
            Add(files);
        }

        public PlayList(List<string> files, ListView listView)
            : this(listView)
        {
            Add(files);
        }

        public PlayList(ListView listView)
        {
            filesList = new List<Song>();
            shuffleHistory = new List<int>();
            queuedFiles = new List<int>();
            shuffle = false;
            songCount = 0;
            currentShufflePosition = 0;
            currentFileIndex = -1;
            playlistView = listView;

            GridView grid = new GridView();
            grid.AllowsColumnReorder = false;

            GridViewColumn queueColumn = new GridViewColumn { DisplayMemberBinding = new System.Windows.Data.Binding("Queue")};
            queueColumn.Width = 20;
            grid.Columns.Add(queueColumn);

            GridViewColumn timeColumn = new GridViewColumn { DisplayMemberBinding = new System.Windows.Data.Binding("Length") };
            timeColumn.Width = 50;
            grid.Columns.Add(timeColumn);

            GridViewColumn titleColumn = new GridViewColumn { DisplayMemberBinding = new System.Windows.Data.Binding("Title") };
            grid.Columns.Add(titleColumn);

            playlistView.View = grid;

        }
        #endregion

        #region Public methods
        #region Add methods
        public void Add(string file)
        {
            Song a = new Song(file);
            if (a.IsOk)
            {
                filesList.Add(new Song(file));
                playlistView.Items.Add(new { Queue = "", Length = a.Length, Title = a.Name });
                songCount++;
            }
        }

        public void Add(string[] files)
        { 
            int count = files.Length;
            for (int i = 0; i < count; i++)
                Add(files[i]);
            songCount += count;
        }

        public void Add(List<string> files)
        {
            int count = files.Count;
            for (int i = 0; i < count; i++)
                Add(files[i]);
            songCount += count;
        }

        public void AddFolder(string path)
        {
            if (Directory.Exists(path))
            {
                foreach (string type in Settings.Instance.AllowedFileTypes)
                    foreach (string file in Directory.GetFiles(path, type))
                        Add(file);
                foreach (string dir in Directory.GetDirectories(path))
                    AddFolder(dir);
            }
        }
        #endregion

        #region Remove methods
        public void Remove(int index)
        {
            if (index < 0 || index >= songCount)
                return;
            if (queuedFiles.Contains(index))
                queuedFiles.Remove(index);
            if (shuffleHistory.Contains(index))
                queuedFiles.Remove(index);
            filesList.RemoveAt(index);
        }

        public void Remove(int[] indexes)
        {
            List<int> temp = new List<int>();
            for (int i = 0; i < indexes.Length; i++)
                temp.Add(indexes[i]);
            Remove(temp);
            temp.Clear();
            GC.ReRegisterForFinalize(temp);
        }

        public void Remove(List<int> indexes)
        {
            indexes.Sort();
            for (int i = indexes.Count - 1; i >= 0; i--)
                Remove(indexes[i]);
        }
        #endregion

        #region Get song methods
        public Song GetNextSong()
        {
            if (songCount == 0)
                return null;
            if (queuedFiles.Count != 0)
            {
                Song a = filesList[queuedFiles[0]];
                currentFileIndex = queuedFiles[0];
                unQueueSong(queuedFiles[0]);
            }
            if (shuffle)    // ce shufflamo
            {
                if (currentShufflePosition < shuffleHistory.Count - 1)   //ce nismo na zadnjem komadu iz shuffla
                {
                    currentShufflePosition++;
                    return filesList[shuffleHistory[currentShufflePosition]];
                }

                Random random = new Random();
                if (shuffleHistory.Count == S_maxShuffleLength)
                    shuffleHistory.RemoveAt(0);
                int a;
                while (true)
                {
                    a = random.Next(songCount);
                    if (!shuffleHistory.Contains(a) || songCount < S_maxShuffleLength)
                        break;
                }
                if (currentShufflePosition < S_maxShuffleLength)
                    currentShufflePosition++;
                shuffleHistory.Add(a);
                currentFileIndex = a;
            }
            else     //ce ne shufflamo
            {
                currentFileIndex = (currentFileIndex + 1) % songCount;
            }
            playlistView.SelectedIndex = currentFileIndex;
            return filesList[currentFileIndex];
        }

        public Song GetSong(int index)
        {
            if (index < 0 || index > songCount)
                return null;
            return filesList[index];
        }

        public Song GetPrevSong()
        {
            if (songCount == 0)
                return null;
            if (shuffle)    // ce shufflamo
            {
                if (currentShufflePosition > 0)
                    currentShufflePosition--;
                currentFileIndex =  shuffleHistory[currentShufflePosition];
            }
            else          // ce ne shufflamo
            {
                if (currentFileIndex == 0)
                    currentFileIndex = songCount - 1;
                else
                    currentFileIndex--;
            }
            playlistView.SelectedIndex = currentFileIndex;
            return filesList[currentFileIndex];
        }

        public Song GetLastSong()
        {
            if (songCount == 0)
                return null;
            else
                return filesList[songCount - 1];
        }
        #endregion

        #region Queue methods

        public void AutoQueueUnqueue()
        {
            QueueUnqueueSong(playlistView.SelectedIndex);
        }

        public void QueueUnqueueSong(int index)
        {
            if (index < 0 || index >= songCount)
                return;
            Song a = GetSong(index);
            if (queuedFiles.Contains(index)) // unqueue
            {
                unQueueSong(index);
            }
            else               // queue
            {
                queuedFiles.Add(index-1);
                PlayListLine line = new PlayListLine();
                line.Length = a.Length;
                line.Queue = queuedFiles.Count.ToString();
                line.Title = a.Name;
                playlistView.Items[index] = line;
            }
        }

        private void unQueueSong(int index)
        {
            //int b = queuedFiles[index];
            Song a = GetSong(index);
            queuedFiles.Remove(index);
            PlayListLine line = new PlayListLine();
            line.Length = a.Length;
            line.Queue = "";
            line.Title = a.Name;
            playlistView.Items[index + 1] = line;    //+1 zatadi indexov, ki se v listi začnejo z 1, v qued listi pa z 0
            updateQuedSongNumbers(); 
        }

        private void updateQuedSongNumbers()
        {
            if (queuedFiles.Count == 0)
                return;
            Song a;
            PlayListLine line;
            for (int i = 0; i < queuedFiles.Count; i++)
            {
                a = GetSong(queuedFiles[i]); 
                line = new PlayListLine();
                line.Length = a.Length;
                line.Queue = (1+i).ToString();
                line.Title = a.Name;
                playlistView.Items[queuedFiles[i]+1] = line;    //+1 zatadi indexov, ki se v listi začnejo z 1, v qued listi pa z 0

            }
        }
        #endregion
        #endregion

        #region Public properties
        public bool Shuffling
        {
            get { return shuffle; }     //vrnemo shuffle stanje
            set                         //nastavimo shuffle stanje in nastavimo vrednosti
            { 
                shuffle = value;
                if (value == false)
                    shuffleHistory.Clear();
                else
                    currentShufflePosition = 0;
            }
        }

        public int PlayingSongIndex
        {
            get { return currentFileIndex; }
            set { currentFileIndex = value; }
        }

        public int SongCount
        {
            get { return songCount; }
        }

        public ListView ListView
        {
            get { return playlistView; }
        }
        #endregion

    }
}
